package com.zh.zcy.service.impl;

import com.zh.zcy.dto.BuyDto;
import com.zh.zcy.entity.Product;
import com.zh.zcy.entity.ZcySyncOperation;
import com.zh.zcy.mapper.FrontJsonMapper;
import com.zh.zcy.mapper.ProductMapper;
import com.zh.zcy.service.FrontJsonService;
import com.zh.zcy.untils.RedLockUtil;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

@Service
public class FrontJsonServiceImpl implements FrontJsonService {

    @Autowired
    private FrontJsonMapper frontJsonMapper;

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private TransactionTemplate transactionTemplate;

//    @Autowired
//    private RedLockUtil redLockUtil;

    private static final String ORDER_LOCK_KEY = "order_lockq";

    @Override
    public void save(ZcySyncOperation save) {
        frontJsonMapper.insert(save);
    }

    @Override
    public Product selectById(BuyDto dto) {
        //没有锁的情况
        Product p = new Product();
        p = productMapper.selectById(dto.productId);
        if(p.num-dto.getCount() > 0){
            p.setNum(p.num-dto.getCount());
            productMapper.updateById(p);
        }

        /*单节点分布式锁
        RLock r = redissonClient.getLock(ORDER_LOCK_KEY);
        r.lock();
        try {
            p = productMapper.selectById(dto.productId);
            if(p.num-dto.getCount() > 0){
                p.setNum(p.num-dto.getCount());
                productMapper.updateById(p);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        r.unlock();*/

        /*三个节点分布式锁
        RLock rLock = null;
        // 尝试获取 RedLock（等待5秒，锁持有30秒）
        rLock = redLockUtil.tryRedLock(ORDER_LOCK_KEY, 2000, 10000);
        if (rLock == null) {
            throw new RuntimeException("获取锁失败，请重试");
        }
        try{
            p = productMapper.selectById(dto.productId);
            if(p.num-dto.getCount() > 0){
                p.setNum(p.num-dto.getCount());
                productMapper.updateById(p);
            }
        } catch (Exception e){
            System.out.println("线程中断。。。。。");
            Thread.currentThread().interrupt();
        } finally {
            // 释放锁
            redLockUtil.releaseRedLock(rLock);
        }*/

        return p;
    }

    /**
     * 编程式事务
     * 回滚方式一
     * TransactionCallbackWithoutResult--无返回值
     */
    public void testRollback1(){

        // 这里执行数据库查询的SQL，查询失败也不需要回滚

        // 需要回滚的代码块
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                try {
                    //这里执行数据库增删改操作，失败需要回滚
                } catch (Exception e){
                    //异常中进行回滚
                    status.setRollbackOnly();//这是回滚代码
                }
            }
        });
    }

    /**
     * 编程式事务
     * 回滚方式二
     * TransactionCallback--有返回值
     */
    public void testRollback2(){

        // 这里执行数据库查询的SQL，查询失败也不需要回滚

        //需要回滚的代码块
        transactionTemplate.execute(new TransactionCallback<Object>() {
            @Override
            public Object doInTransaction(TransactionStatus transactionStatus) {
                try{
                    //  失败需要回滚的代码
                    return new Object();
                }catch (Exception e){
                    // 回滚
                    transactionStatus.setRollbackOnly();
                    return null;
                }
            }
        });
    }
}
